#pragma once

#include <cstdio>
#include <cstring>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "socket.h"
#include <functional>
#include "esp_log.h"

namespace tcp_client
{
    static const int NUM = 1024;
    static const char *TAG = "tcp_client";
    typedef std::function<void(int, uint16_t, std::string)> func_t;

    class tcpClient
    {
    public:
        tcpClient(const std::string &serverip, const uint16_t serverport)
            : serverip_(serverip), serverport_(serverport)
        {
        }

        ~tcpClient()
        {
            close(sock_);
        }

        void initClient()
        {
            // 创建TCP socket
            sock_ = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
            if (sock_ < 0)
            {
                ESP_LOGE(TAG, "socket create failed");
                return;
            }
            else
            {
                ESP_LOGI(TAG, "socket create success");
            }
        }

        void start()
        {
            // 连接TCP服务器
            struct sockaddr_in server_addr;
            memset(&server_addr, 0, sizeof(server_addr));
            server_addr.sin_family = AF_INET;
            server_addr.sin_port = htons(serverport_);
            server_addr.sin_addr.s_addr = inet_addr(serverip_.c_str());
            if (connect(sock_, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0)
            {
                ESP_LOGE(TAG, "connect failed");
                return;
            }
            else
            {
                ESP_LOGI(TAG, "connect success");
                std::string msg = "hello tcp server";
                while (true)
                {
                    write(sock_, msg.c_str(), msg.size());

                    char buffer[NUM];
                    int n = read(sock_, buffer, sizeof(buffer) - 1);
                    if (n > 0)
                    {
                        // 目前我们把读到的数据当成字符串
                        buffer[n] = 0;
                        printf("Server回显# %s\n", buffer);
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }

    private:
        std::string serverip_;
        uint16_t serverport_;
        int sock_;
    };
}